//Version 15 - Parte A y B:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>

int parsing(char line[], char* args[], char type1[], char type2[]);
void command(char* args[], char* path);
void seek(char *arreglo[]);
void changeDir(char* args[], char* path);
void showPrompt();

char* directories[100];
char* PATH;
int flagamp;

int main(int argc, char *argv[]){
    printf("--------------------------BAASH--------------------------\n");
    char* args[100];   
    char line[1024];
    int cantarg;
    
    PATH = getenv("PATH");
    parsing(PATH, directories, ":",":");
        
    while(1){  
        
        flagamp=0;
        showPrompt();                  
        
        if (fgets(line, 1024, stdin) == NULL) return 0;
			else{
                   cantarg=parsing(line, args, " ", " \n");    //Parsea la linea de entrada.
                   if(strcmp(args[cantarg-1],"&")==0){
                                args[cantarg-1] = NULL;
                                cantarg--;
                                flagamp=1;
                   }
            if(cantarg>=3){
					printf("PIPELINE %i\n",cantarg);	  //Si el usuario ingreso mas de 3 argumentos,se crea el pipe
				}else command(args, getcwd(NULL, 0));     //sino, interpreta el comando (agrs[0])
        }
    }
    
    return 0;
}

//Muestra el prompt
void showPrompt(){
    printf("%s # %s > ", getenv("LOGNAME"),(char*) getcwd(NULL, 0));            
}

//Parsea una linea
int parsing(char line[], char* args[], char type1[], char type2[]){ 
    int i = 0;
    args[i] = strtok(line, type1);    
    while((args [i]) != NULL) {
                i++;
				args[i] = strtok (NULL, type2);
    }
    return i;
}

//Interpreta el comando: si es cd llama a changedir(), si no es cd llama a seek().
void command(char* args[], char* path){
    if(strcmp(args[0], "exit\n") == 0) exit(1);
    if(strcmp(args[0], "\n") == 0) return;
    if(strcmp(args[0], "cd") == 0) changeDir(args, path);
		else seek(args);
}

//Cambia el directorio (comando cd)
void changeDir(char* args[], char* path){
        if( chdir(args[1]) != 0 ) perror("Command not found\n");
                else path = (char*) getcwd(NULL, 0);
}

//Busqueda de secuencia PATH, caminos abusolutos y relativos 
void seek(char *args[]){
    char str[200];
    int flag = 0;
    int num = 0;
    pid_t pid;

    //En cada uno de los PATH debo probar si esta el comando 
    
    if ( (pid = fork()) == 0){	// HIJO ---------------------------------------------------------------------------------------
		
	  if(args[0][0]=='.'){		//Si comienza con un ./ o   ../
			char * aux1;
			char * aux2;
			int status = 0;
    
            aux1 = strtok(args[0],"/");     
            aux2 = aux1;
    
            while((status == 0)&&((aux1 = strtok(NULL,"/"))!= NULL)){
				status = chdir(aux2);	
				aux2 = aux1;            
			}                                       
    
            char* path = (char*) getcwd(NULL, 0);   //Encuentra el pwd.
			strcat (path,"/");
			strcat (path,aux2);     
			strncpy(str,path,sizeof(str));
    
			//Quita el final de linea, solo si no habia & (ya que si habia, fue quitado):
			if (flagamp==0){              
				int j=0;
				int n=0;
				while(str[j]!='\0')j++;                
				for(n=0;n<j;n++) if((str[n]=='\n')||(str[n]=='\0'))str[n]='\0';
			}
                        
			if((access(str,F_OK))==0){
					execv(str, args);
					exit(1);
			}
			else{
				perror("Error, File not found \n");
				exit(1);
			}
		}
		else{	//Si no comienza con un ./ o / 
					int i = 0;        
					char* dir[100];
                
					while( directories[i] != NULL ){                    
						//Busca en PATH el comando especificado:    
						
						//Arma el string = path + / + comando:    
						dir[i] = directories[i];
						strcpy (str, dir[i]);                            
						strcat (str, "/");
						strcat(str, args[0]);
						
						//Quita el final de linea, solo si no habia & (ya que si habia, fue quitado):
						if (flagamp==0){
							int j = 0;
							while(str[j]!='\0')j++;                
							if ( args[1] != NULL ) str[j] = '\0';
                                 else str[j-1] = '\0';
						}
						//Si lo encuentra lo ejecuta:
						if( (access(str,F_OK)) == 0 ){
							execv(str, args);
							num = 1;
						}
						else i++;	//Si no lo encientra incrementa i, para buscar en otro directorio.
					}
                
					//Si no encontro el comando en todo PATH muestra un mensaje de error:
					if( num == 0 ){
						perror("File not found");
						exit(1);
					}
        }            
	}
	else if ( pid>0 )flag =-1; // PADRE ---------------------------------------------------------------------------------------
                
    if(flagamp!=1){  					//Si no habia &, espera al hijo
		waitpid(pid, &flag, 0);         
		args=NULL;                      
	}
	else {								 //Si habia &, no lo espera
		args = NULL;
		waitpid(pid, &flag, WNOHANG);
	}
        
}
